﻿using mozhi.smarterp.Business.Enums;
using mozhi.smarterp.Business.Sales.Repositories;
using mozhi.smarterp.Business.Sales.Services;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Volo.Abp.Application.Dtos;

namespace mozhi.smarterp.Business.Sales.Orders
{
    public class SaleOrderAppService : BusinessAppService, ISaleOrderAppService
    {
        private ISaleOrderRepository _repository;
        private SaleOrderManager _manager;

        public SaleOrderAppService(ISaleOrderRepository repository, SaleOrderManager manager)
        {
            _repository = repository;
            _manager = manager;
        }

        public async Task<SaleOrderDto> CreateAsync(SaleOrderCreateDto input)
        {
            var order = await _manager.GetAsync(null, input.Date, input.IncludeTax, input.CustomerId, input.Address, input.CurrencyId, input.ExchangeRate,
                input.DepartmentId, input.SalePersonId, input.PaymentTermId, input.Comment, input.Type);

            input.Items = input.Items ?? new List<SaleOrderItemCreateDto>();

            var orderItems = new List<SaleOrderItem>();

            foreach (var item in input.Items)
            {
                var orderItem = await _manager.GetItemAsync(null, item.ProductId, item.SaleUnitId, item.SaleQuantity, item.Price, item.TaxRateId, item.IsGift, item.Remark);

                orderItems.Add(orderItem);
            }

            order.ChangeItems(orderItems);

            order = await _repository.InsertAsync(order);

            var result = ObjectMapper.Map<SaleOrder, SaleOrderDto>(order);

            return result;
        }

        public async Task DeleteAsync(Guid id)
        {
            await _manager.DeleteAsync(id);
        }

        public async Task<SaleOrderDto> GetAsync(Guid id)
        {
            var order = await _repository.GetAsync(id);

            var result = ObjectMapper.Map<SaleOrder, SaleOrderDto>(order);

            return result;
        }

        public async Task<PagedResultDto<SaleOrderDto>> GetListAsync(SaleOrderPagedResultRequestDto filter)
        {
            var orders = await _repository.GetPagedListAsync(filter.Keyword, filter.Number, filter.CustomerId, filter.CurrencyId, filter.SkipCount, filter.MaxResultCount, filter.Sorting);

            var count = await _repository.GetCountAsync(filter.Keyword, filter.Number, filter.CustomerId, filter.CurrencyId, null);

            var items = ObjectMapper.Map<List<SaleOrder>, List<SaleOrderDto>>(orders);

            return new PagedResultDto<SaleOrderDto>()
            {
                Items = items,
                TotalCount = count
            };
        }

        public async Task<Guid> PushAdvanceReceiptAsync(Guid id)
        {
            var collection = await _manager.PushAdvanceReceiptAsync(id);

            return collection.Id.Value;
        }

        public async Task<Guid> PushSaleDeliveryAsync(Guid id)
        {
            var saleDelivery = await _manager.PushSaleDeliveryAsync(id);

            return saleDelivery.Id;
        }

        public async Task<SaleOrderDto> UpdateAsync(SaleOrderUpdateDto input)
        {
            var order = await _manager.GetAsync(input.Id, input.Date, input.IncludeTax, input.CustomerId, input.Address, input.CurrencyId, input.ExchangeRate,
               input.DepartmentId, input.SalePersonId, input.PaymentTermId, input.Comment, input.Type);

            input.Items = input.Items ?? new List<SaleOrderItemUpdateDto>();

            var orderItems = new List<SaleOrderItem>();

            foreach (var item in input.Items)
            {
                var orderItem = await _manager.GetItemAsync(item.Id, item.ProductId, item.SaleUnitId, item.SaleQuantity, item.Price, item.TaxRateId, item.IsGift, item.Remark);

                orderItems.Add(orderItem);
            }

            order.ChangeItems(orderItems);

            order = await _repository.InsertAsync(order);

            var result = ObjectMapper.Map<SaleOrder, SaleOrderDto>(order);

            return result;
        }

        public async Task<SaleOrderDto> UpdateStatusAsync(Guid id, DocumentStatusType status)
        {
            var order = await _manager.UpdateStatusAsync(id, status);

            await _repository.UpdateAsync(order);

            var result = ObjectMapper.Map<SaleOrder, SaleOrderDto>(order);

            return result;
        }
    }
}
